﻿/**
 *
 * eeprom.c
 *
 *  Created on: 2016-11-12
 *      Author: chenshisheng
 */

#include "eeprom.h"
#include "weight.h"

#define START_ADDR FLASH_DATA_START_PHYSICAL_ADDRESS

static struct
{
    uint32_t addr;
}_infos[Eeprom_Content_Max];

static const struct
{
    uint8_t size;
} _contentList[Eeprom_Content_Max] =
{
    {sizeof(Weight_CalibrationParameter_t)},
};

void Eeprom_Init(void)
{
    Eeprom_Content_t c;
    uint32_t addr;

    addr = START_ADDR;
    for(c = 0; c < Eeprom_Content_Max; c++)
    {
        _infos[c].addr = addr;
        addr += _contentList[c].size + 1;
    }
}

static uint8_t _CheckSum(const void *data, size_t size)
{
    uint8_t checkSum, i;
    const uint8_t *vdata;

    vdata = data;
    checkSum = 0x55;
    for(i = 0; i < size; i++)
    {
        checkSum ^= vdata[i];
    }

    return checkSum;
}

int8_t Eeprom_Store(Eeprom_Content_t content, const void *dataIn, uint8_t size)
{
    uint32_t addr;
    uint8_t i;
    const uint8_t *vdata;

    if(size != _contentList[content].size)
    {
        return -1;
    }

    FLASH_Unlock(FLASH_MEMTYPE_DATA);

    addr = _infos[content].addr;
    vdata = dataIn;
    for(i = 0; i < size; i++)
    {
        FLASH_ProgramByte(addr, vdata[i]);
        FLASH_WaitForLastOperation(FLASH_MEMTYPE_DATA);

        addr += 1;
    }

    FLASH_ProgramByte(addr, _CheckSum(dataIn, size));
    FLASH_WaitForLastOperation(FLASH_MEMTYPE_DATA);

    FLASH_Lock(FLASH_MEMTYPE_DATA);
    return 0;
}

int8_t Eeprom_Load(Eeprom_Content_t content, void *dataOut, uint8_t size)
{
    uint32_t addr;
    uint8_t i, checkSum;
    uint8_t *vdata;

    if(size != _contentList[content].size)
    {
        return -1;
    }

    addr = _infos[content].addr;
    vdata = dataOut;
    for(i = 0; i < size; i++)
    {
        vdata[i] = FLASH_ReadByte(addr);
        FLASH_WaitForLastOperation(FLASH_MEMTYPE_DATA);

        addr += 1;
    }

    checkSum = FLASH_ReadByte(addr);
    FLASH_WaitForLastOperation(FLASH_MEMTYPE_DATA);

    FLASH_Lock(FLASH_MEMTYPE_DATA);
    return (checkSum == _CheckSum(dataOut, size)) ? 0 : -1;
}

int8_t Eeprom_Delete(Eeprom_Content_t content)
{
    uint8_t i;
    uint8_t size;
    uint32_t addr;

    FLASH_Unlock(FLASH_MEMTYPE_DATA);

    addr = _infos[content].addr;
    size = _contentList[content].size + 1;
    for(i = 0; i < size; i++)
    {
        FLASH_ProgramByte(addr, 0xff);
        FLASH_WaitForLastOperation(FLASH_MEMTYPE_DATA);

        addr += 1;
    }

    FLASH_Lock(FLASH_MEMTYPE_DATA);
    return 0;
}
